package org.opens.netty.chatServer.server.handle;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.opens.netty.chatServer.message.RpcRequestMessage;
import org.opens.netty.chatServer.message.RpcResponseMessage;
import org.opens.netty.chatServer.server.service.ServiceFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

@ChannelHandler.Sharable
public class RpcRequestHandle extends SimpleChannelInboundHandler<RpcRequestMessage> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequestMessage msg) throws Exception {
        RpcResponseMessage rpcResponseMessage = new RpcResponseMessage();
        try {
            Object serviceImpl = ServiceFactory.getService(Class.forName(msg.getInterfaceName()));
            Method method = serviceImpl.getClass().getMethod(msg.getMethodName(), msg.getParameterTypes());
            Object returnValue = method.invoke(serviceImpl, msg.getParameterValue());
            // 序列保持一致
            rpcResponseMessage.setSequenceId(msg.getSequenceId());
            rpcResponseMessage.setReturnValue(returnValue);
        } catch (Exception e) {
            // 避免将大量的错误信息返回给rpc客户端, 只返回必要的信息
            // e.getCause()表示拿到异常起因
            rpcResponseMessage.setExceptionValue(new Exception("远程调用出错: " + e.getCause().getMessage()));
        }
        ctx.writeAndFlush(rpcResponseMessage);
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        RpcRequestMessage rpcRequestMessage = new RpcRequestMessage(
                1,
                "org.opens.netty.chatServer.server.service.HelloService",
                "sayHello",
                String.class,
                new Class[]{String.class},
                new Object[]{"123"}
        );

        Object serviceImpl = ServiceFactory.getService(Class.forName(rpcRequestMessage.getInterfaceName()));
        Method method = serviceImpl.getClass().getMethod(rpcRequestMessage.getMethodName(), rpcRequestMessage.getParameterTypes());
        Object returnValue = method.invoke(serviceImpl, rpcRequestMessage.getParameterValue());
        System.out.println(returnValue);
    }

}
